package com.mxdx.edu.common.log;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.mxdx.edu.common.DateFormatUtils;
import com.mxdx.edu.common.DateStyle;

/**
 * 日志工具类
 * 
 * @author zyc
 * @date 2015年4月20日
 */
public class AppLogger implements Serializable{
 
    private static final long serialVersionUID = 1L;
    
    private Logger logger;
    

    public AppLogger(Class<?> c) {
        this.logger = LogManager.getLogger(c);
    }
    
    public AppLogger(String name) {
        this.logger = LogManager.getLogger(name);
    }
    
    /**
     * 确定输出一条info信息，用于方法执行中间记录执行信息
     * @param msg
     */
    public void doInfo(String msg, Object data) {
        if(data != null) {
            if(data instanceof String) {
                logger.info(String.format("msg: %s ## data: %s", msg, data));
            } else {
                logger.info(String.format("msg: %s ## data: %s", msg, JSON.toJSONString(data)));
            }
            
        } else {
            logger.info(String.format("msg: %s", msg));
        }
        
    }
    
    /**
     * 确定输出一条错误信息， 用于方法执行中间记录执行错误信息， 用于方法内部单独使用错误输出的设置。
     * @param errorMsg
     * @param e
     */
    public void doError(String errorMsg, Throwable e) {
        logger.error(String.format("errorMsg: %s ## ex: %s", errorMsg, getExceptionTrace(e)));
    }
    
    /**
     * 确定输出一条错误信息， 用于方法执行中间记录执行错误信息， 用于方法内部单独使用错误输出的设置。
     * @param errorMsg
     * @param data
     * @param e
     */
    public void doError(String errorMsg, Object data, Throwable e) {
        logger.error(String.format("errorMsg: %s ## data: %s ## ex: %s", errorMsg, (data == null) ? "" : JSON.toJSONString(data), getExceptionTrace(e)));
    }
    
    /**
     * 确定输出一条错误信息， 用于方法执行中间记录执行错误信息， 用于方法内部单独使用错误输出的设置。
     * @param errorMsg
     * @param data
     */
    public void doError(String errorMsg, Object data) {
        logger.error(String.format("errorMsg: %s ## data: %s", errorMsg, (data == null) ? "" : JSON.toJSONString(data)));
    }

    /**
     * 日志开始方法，在方法执行的开始位置必须标注；不使用log4j获取方法信息，因为这个方法会影响性能
     * 
     * @param method
     */
    public void entry(String cip, String method) {
        LogModel<Object> lm = new LogModel<Object>();
        lm.setMethod(method);
        lm.setCip(cip);
        long startT = System.currentTimeMillis();
        lm.setCt(startT);
        SysLogModelContext.setlm(lm);
    }

    /**
     * 记录系统日志
     * 
     * @param msg
     */
    public void info(Object msg) {
        LogModel<Object> lm = SysLogModelContext.getLm();
        // lm.setService(logger.getName());
        
        String method = lm.getMethod();
        if (method == null) {
            lm.setMethod("no log entry");
        }
        lm.setData(msg);
        long startT = lm.getCt();
        if (startT > 0) {
            long endT = System.currentTimeMillis();
            lm.setT(DateFormatUtils.DateToString(new Date(startT),
                    DateStyle.YYYY_MM_DD_HH_MM_SS_SSS));
            lm.setCt((int) (endT - startT));
        }
        logger.info(JSON.toJSON(lm));
        SysLogModelContext.removeLm();
    }
    
    /**
     * 记录系统日志
     * 
     * @param msg
     */
    public void debug(Object msg) {
        LogModel<Object> lm = SysLogModelContext.getLm();
        // lm.setService(logger.getName());
        
        String method = lm.getMethod();
        if (method == null) {
            lm.setMethod("no log entry");
        }
        lm.setData(msg);
        long startT = lm.getCt();
        if (startT > 0) {
            long endT = System.currentTimeMillis();
            lm.setT(DateFormatUtils.DateToString(new Date(startT),
                    DateStyle.YYYY_MM_DD_HH_MM_SS_SSS));
            lm.setCt((int) (endT - startT));
        }
        logger.debug(JSON.toJSON(lm));
        SysLogModelContext.removeLm();
    }

    /**
     * 写错误信息
     * 
     * @param msg
     * @param e
     */
    public void error(Object msg, Throwable e) {
        LogModel<Object> lm = SysLogModelContext.getLm();
        String method = lm.getMethod();
        if (method == null) {
            lm.setMethod("no log entry");
        }

        lm.setData(msg);
        lm.setEx(getExceptionTrace(e));
        long startT = lm.getCt();
        if (startT > 0) {
            long endT = System.currentTimeMillis();
            lm.setT(DateFormatUtils.DateToString(new Date(startT),
                    DateStyle.YYYY_MM_DD_HH_MM_SS_SSS));
            lm.setCt((int) (endT - startT));
        }
        logger.error(JSON.toJSON(lm));
        SysLogModelContext.removeLm();
       
    }
    
    
    /**
     * 写错误信息
     * 
     * @param msg
     */
    public void error(Object msg) {
        LogModel<Object> lm = SysLogModelContext.getLm();
        String method = lm.getMethod();
        if (method == null) {
            lm.setMethod("no log entry");
        }

        lm.setData(msg);
        long startT = lm.getCt();
        if (startT > 0) {
            long endT = System.currentTimeMillis();
            lm.setT(DateFormatUtils.DateToString(new Date(startT),
                    DateStyle.YYYY_MM_DD_HH_MM_SS_SSS));
            lm.setCt((int) (endT - startT));
        }
        logger.error(JSON.toJSON(lm));
        SysLogModelContext.removeLm();
       
    }
    
    
    /**
     * 日志中只记录简单的错误信息， e.getMessage()的信息
     * 
     * @param msg
     * @param e
     */
    public void errorOnlyExceptionMsg(Object msg, Exception e) {
        LogModel<Object> lm = SysLogModelContext.getLm();
        String method = lm.getMethod();
        if (method == null) {
            lm.setMethod("no log entry");
        }

        lm.setData(msg);
        if(e != null) {
            lm.setEx(e.getMessage());
        }
        long startT = lm.getCt();
        if (startT > 0) {
            long endT = System.currentTimeMillis();
            lm.setT(DateFormatUtils.DateToString(new Date(startT),
                    DateStyle.YYYY_MM_DD_HH_MM_SS_SSS));
            lm.setCt((int) (endT - startT));
        }
        logger.error(JSON.toJSON(lm));
        SysLogModelContext.removeLm();
       
    }

    /**
     * 获取异常堆栈信息
     * @param cause
     * @return
     */
    private static String getExceptionTrace(Throwable cause) {
        if(cause == null) return "";
        String print = null;
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        PrintWriter wrt = new PrintWriter(bout);
        cause.printStackTrace(wrt);
        wrt.close();
        print = bout.toString();
        return print;
    }
    
    


}
